package com.lotter.api.service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lotter.common.context.YcContext;
import com.lotter.common.enumobject.AvailableEnum;
import com.lotter.common.enumobject.CashRecordEnum;
import com.lotter.common.enumobject.CashStatusEnum;
import com.lotter.common.enumobject.IswinningEnum;
import com.lotter.common.enumobject.OperationType;
import com.lotter.common.enumobject.OrderstatusEnum;
import com.lotter.common.enumobject.UserAccountTypeEunm;
import com.lotter.common.enumobject.WinpayEnum;
import com.lotter.common.enumobject.WinpayflowEnum;
import com.lotter.common.exception.LotterCusException;
import com.lotter.common.invocation.BaseConditionVO;
import com.lotter.common.util.BigdecimalUtil;
import com.lotter.common.util.DateUtil;
import com.lotter.common.util.RoomUtil;
import com.lotter.common.util.StringUtil;
import com.lotter.context.CaipiaoKongContent;
import com.lotter.dao.CashRecordMapper;
import com.lotter.dao.LotteryOrderMapper;
import com.lotter.dao.OrderDetailsMapper;
import com.lotter.dao.UserAccountMapper;
import com.lotter.dao.WinpayflowDao;
import com.lotter.model.caipiao.CashRecord;
import com.lotter.model.order.LotteryOrder;
import com.lotter.model.order.OrderDetails;
import com.lotter.model.user.UserAccount;
import com.lotter.model.winpayflow.WinPayFlowVo;


@Service
public class LotteryOrderService {
	
	
	@Autowired
	private LotteryOrderMapper lotteryOrderMapper;
	
	@Autowired
	private OrderDetailsMapper orderDetailsMapper ;

	@Autowired
	private CashRecordMapper cashRecordMapper;
	
	@Autowired
	private WinpayflowDao winpayflowDao;
	
	@Autowired
	private UserAccountMapper userAccountMapper;
	
	/**
	 * 个人订单
	 * @param result
	 * @param vo
	 * @return
	 * @throws LotterCusException
	 */
	public Map<String,Object> findLotteryOrderList( Map<String,Object> result,
			Integer pageNum,Integer numPerPage,Long uid,Integer iswinning) 
			throws LotterCusException{
		BaseConditionVO vo = new BaseConditionVO();
		vo.setKeywords(uid);
		vo.setNumPerPage(numPerPage);
		vo.setPageNum(pageNum);
		if(iswinning != null){
		    vo.setType(iswinning);
		}
		result.put("iswinningenum", IswinningEnum.toJSONString());
		List<LotteryOrder> list = lotteryOrderMapper.findLotteryOrderByPage(vo);
		result.put("data", list);
		return result;
	}
	
	
	/**
	 * 个人订单
	 * @param result
	 * @param vo
	 * @return
	 * @throws LotterCusException
	 */
	public Map<String,Object> findHourserOrderInfo( Map<String,Object> result,BaseConditionVO vo,Long uid) 
			throws LotterCusException{
		vo.setKeywords(uid);
		result.put("iswinningenum", IswinningEnum.toJSONString());
		List<LotteryOrder> list = lotteryOrderMapper.findLotteryOrderByPage(vo);
		result.put("data", list);
		return result;
	}
	
	
	//下订单
	@Transactional(rollbackFor=Exception.class)
	public void insertorder(UserAccount userAccount,Long ownerid , List<OrderDetails> orderDetails,
		    Integer multiple) throws Exception{
		
			LotteryOrder lotteryOrder = new LotteryOrder();
			lotteryOrder.setUid(userAccount.getId());
			lotteryOrder.setOwnerid(ownerid);
			lotteryOrder.setIswinning(IswinningEnum.CLOSE_WINNING.getCode());
			lotteryOrder.setAvailable(AvailableEnum.AVAILABLE.getCode());
			lotteryOrder.setMultiple(multiple);
			lotteryOrder.setGametype(0);//足彩
			lotteryOrder.setCreatedate(new Date());
			lotteryOrder.setOrderstatus(OrderstatusEnum.PAID.getCode());
			
			Long totalprice = 200L * multiple;
			lotteryOrder.setTotalprice(totalprice);
			
			BigDecimal expectprize = new  BigDecimal(totalprice);
			//处理商品明细
			List<CashRecord> list = null;
			HashSet<String> set = new HashSet<String>();
			for(OrderDetails details:orderDetails){
				set.add(details.getPid());
				details.setIswinning(IswinningEnum.CLOSE_WINNING.getCode());
				// 1 判断场次属于那一天
				String today_matchIds =CaipiaoKongContent.get_today_matchIds();
				String tomorrow_matchIds =CaipiaoKongContent.get_tomorrow_matchIds();
				//当天场次
				int number = 0 ;
				if(StringUtil.isNotBlank(today_matchIds) && StringUtil.contains
						(today_matchIds, details.getPid().toString())){
					number = 1 ;
					
				}//明天场次
				else if(StringUtil.isNotBlank(tomorrow_matchIds) && StringUtil.contains
						(tomorrow_matchIds, details.getPid().toString())){
					number = 2 ;
				}//后天场次
				else{
					number = 3 ;
				}
				
				switch (number) {
				case 1:
					String today_data = CaipiaoKongContent.findMapData("today_data");
					list =JSON.parseArray(today_data, CashRecord.class);
					break;
				case 2:
					String tomorrow_data = CaipiaoKongContent.findMapData("tomorrow_data");
					list =JSON.parseArray(tomorrow_data, CashRecord.class);
					break;
				case 3:
					String third_data = CaipiaoKongContent.findMapData("third_data");
					list =JSON.parseArray(third_data, CashRecord.class);
					break;
				default:
					break;
				}
				
				//获取基础数据   拿到赔率
				for(CashRecord cashRecord : list){
					if(!cashRecord.getId().equals(details.getPid().toString()))
						continue;
					 Object obj = null ;
					 details.setHometeam(cashRecord.getHome_team());
	  				 details.setAwayteam(cashRecord.getAway_team());
	  				 details.setWeekday(cashRecord.getWeekday());
	  				 details.setOfficial_num(cashRecord.getOfficial_num());
					 //胜平负 
		   			 if(details.getPtype() == OperationType.current_spf.getCode()){
		   				 obj = cashRecord.getCurrent_spf();
		   			 }//让球胜平负
		   			 else if(details.getPtype() == OperationType.current_rqspf.getCode()){
		   				 obj = cashRecord.getCurrent_rqspf();
		   			 }//比分
		   			 else if(details.getPtype() == OperationType.current_bf.getCode()){
		   				 obj = cashRecord.getCurrent_bf();
		   			 }//总进球
		   			 else if(details.getPtype() == OperationType.current_jqs.getCode()){
		   				 obj = cashRecord.getCurrent_jqs();
		   			 }//半全场
		   			 else{
		   				 obj = cashRecord.getCurrent_bqc();
		   			 }
		   			 JSONObject jsb =	JSON.parseObject(obj.toString());
	   			     BigDecimal expectodds = jsb.getBigDecimal(details.getItemtype().toString());
	   			     
	   			     expectprize =expectprize.multiply(expectodds);
		   			 details.setExpectodds(expectodds.setScale(2,BigDecimal.ROUND_HALF_UP));
				}
		     }
			 StringBuffer buffer = new StringBuffer();
			 buffer.append(set.size());
			 buffer.append(" 场.");	
			 buffer.append(orderDetails.size());	
			 buffer.append("串. 方案");	
			 buffer.append(multiple);	
			 buffer.append("倍");	
			 lotteryOrder.setProgramme(buffer.toString());
			 lotteryOrder.setOrderno(RoomUtil.getOrderNo());
			 lotteryOrder.setExpectprize(expectprize.setScale(0).longValue());
		  	 lotteryOrderMapper.insert(lotteryOrder);
			 for(OrderDetails detailsorder:orderDetails){
				 detailsorder.setOid(lotteryOrder.getId());
				 orderDetailsMapper.insert(detailsorder);
			 }
			 winpay_order(userAccount.getId(), totalprice, multiple, orderDetails.size());
	}
	
	
	
	/**
	 * 房主资金流水
	 * @param uid
	 * @param sharebenefit
	 * @throws Exception
	 */
	private void winpay_order(Long userid , long totalprice,Integer multiple,int size) throws Exception{
		
		//第一步  新增流水
		UserAccount userAccount =userAccountMapper.selectByPrimaryKey(userid);
		WinPayFlowVo winpayflow_owner = new WinPayFlowVo();
		winpayflow_owner.setAmount(totalprice);
		winpayflow_owner.setAvailableBefore(userAccount.getAmount());
		long accbalance = totalprice+ userAccount.getAmount().longValue();
		winpayflow_owner.setAccbalance(accbalance);
		winpayflow_owner.setWinpay(WinpayEnum.WINPAY_OUT.getCode());
		winpayflow_owner.setCreatedate(new Date());
		winpayflow_owner.setUid(userid);
		winpayflow_owner.setDesrType(WinpayflowEnum.PURCHASE_ORDER.getCode());
		winpayflowDao.insert(winpayflow_owner);
		
	    //第二部  修改账户信息
		//余额
		long  monkey  = userAccount.getAmount().longValue() - totalprice;
		userAccount.setAmount(monkey);
	
		
		//总出票流水金额
		long payflowamount = userAccount.getPayflowamount() + totalprice;
		userAccount.setPayflowamount(payflowamount);
		//总出票张数
		Integer ballotnum =  userAccount.getBallotnum() + multiple ;
		userAccount.setBallotnum(ballotnum);
		//购买场次
		Integer screeningsnum = userAccount.getScreeningsnum() + size;
		userAccount.setScreeningsnum(screeningsnum);
		userAccountMapper.updateByPrimaryKeySelective(userAccount);
	}
	
	
	
	
	/**
	 * 中奖信息
	 * @param id
	 * @return
	 * @throws LotterCusException
	 */
	public Map<String, Object> winingInfo(Map<String,Object> result, Long id) throws LotterCusException{
		LotteryOrder lotteryOrder =lotteryOrderMapper.selectByPrimaryKey(id);
		if(lotteryOrder == null){
			throw new LotterCusException("没有相关订单");
		}
		result.put("lotteryOrder", lotteryOrder);
		List<OrderDetails> details = orderDetailsMapper.findDetailForOrderByOID(id);
		result.put("details", details);
		return result;
	}
	
	
	
	
	
	
	
	
	
	
	
	//将已经开奖的数据保存到数据库
	@Transactional(rollbackFor=Exception.class)
	public void LotteryWinning() throws LotterCusException{
		//今天
		String phase = DateUtil.date2String(new Date(),YcContext.PATTERN_CONNECT);
		Date date = DateUtil.getDateplusDay(new Date(), -1, null, null, null);
		String lastphase = DateUtil.date2String(date,YcContext.PATTERN_CONNECT);
		List<String> cashRecordList  = cashRecordMapper.findMatchIds(phase,lastphase);
		
		
		//获取今天的彩票站数据
		String currently = CaipiaoKongContent.findMapData("currently");
		if(StringUtil.isNotBlank(currently)){
			  List<CashRecord> list =JSON.parseArray(currently, CashRecord.class);
			  for(CashRecord cashRecord : list){
				  if(cashRecordList.contains(cashRecord.getId()))
					  continue;
				  //没有结束
				  if(cashRecord.getFirst_half().length() == 0){
					  continue;
				  }else if(cashRecord.getFirst_half().length() == 1){
					  cashRecord.setStatus(CashStatusEnum.NOTCONFIRM.getCode());
				  }else{
					  cashRecord.setStatus(CashStatusEnum.FINISH.getCode());
				  }
				  cashRecord.setExecute(CashRecordEnum.UNEXECUTED.getCode());
				  cashRecordMapper.insert(cashRecord);
			  }
		 }
	     //获取昨天数据  直接请求		  
		  String beforedata =  CaipiaoKongContent.getMessage(lastphase);
		  if(StringUtil.isNotBlank(beforedata)){
			  List<CashRecord> beforelist =JSON.parseArray(beforedata, CashRecord.class);
			  for(CashRecord cashRecord : beforelist){
				  if(cashRecordList.contains(cashRecord.getId()))
					  continue;
				  //没有结束
				  if(cashRecord.getFirst_half().length() == 0){
					  continue;
				  }else if(cashRecord.getFirst_half().length() == 1){
					  cashRecord.setStatus(CashStatusEnum.STOP.getCode());
				  }else{
					  cashRecord.setStatus(CashStatusEnum.FINISH.getCode());
				  }
				  cashRecord.setExecute(CashRecordEnum.UNEXECUTED.getCode());
				  cashRecordMapper.insert(cashRecord);
		       }
		  }
	  }
	
	
	
	//开奖业务
	@Transactional(rollbackFor = Exception.class)
	public void LotteryOpen() throws Exception{
		String phase = DateUtil.date2String(new Date(),YcContext.PATTERN_CONNECT);
		Date date = DateUtil.getDateplusDay(new Date(), -1, null, null, null);
		String lastphase = DateUtil.date2String(date,YcContext.PATTERN_CONNECT);
		//查询未执行的开奖场次
		List<CashRecord> list = cashRecordMapper.findCaipiaoDTOList(phase, lastphase, 
				CashStatusEnum.FINISH.getCode(),CashStatusEnum.STOP.getCode(),
				CashRecordEnum.UNEXECUTED.getCode());
		
		if(CollectionUtils.isEmpty(list)){
			cashRecordMapper.updateCashRecordByPhase(phase, lastphase, CashRecordEnum.EXECUTED.getCode());
			return ;
		}
		//处理订单明细
		for(CashRecord cashRecord : list){
			updateOrderDetails(cashRecord);
		}
		
		//获取所有未开奖的订单  
		List<LotteryOrder> LotteryOrderList = lotteryOrderMapper.findLotteryOrderByMap(
				IswinningEnum.CLOSE_WINNING.getCode());
		
		//如果子菜单都已经开奖那么直接兑奖
		if(CollectionUtils.isEmpty(LotteryOrderList)){
			cashRecordMapper.updateCashRecordByPhase(phase, lastphase, CashRecordEnum.EXECUTED.getCode());
			return ;
		}
			
		
		//处理订单表
		for(LotteryOrder lotteryOrder : LotteryOrderList){
			updateLotterOrder(lotteryOrder);
	    }
		
		cashRecordMapper.updateCashRecordByPhase(phase, lastphase, CashRecordEnum.EXECUTED.getCode());		
	}
		
	//更新相关场次的商品订单明细
	private void updateOrderDetails(CashRecord cashRecord) throws Exception{
		//遍历处理订单
		 List<OrderDetails> details = null ;
		 details = orderDetailsMapper.findOrderDetailsByMap(IswinningEnum.CLOSE_WINNING
					.getCode(), cashRecord.getId());
	     if(CollectionUtils.isEmpty(details))
	    	 return;
	     //订单商品处理
	     for(OrderDetails orderDetails : details){
	    	   //获取赔率
	    	 orderDetails.setIswinning(cashRecord.judgeWinOrLose(
	    			 orderDetails.getPtype(), orderDetails.getItemtype()));
	    	 orderDetails.setActualodds(cashRecord.getActualOdds(
	    			 orderDetails.getPtype(), orderDetails.getItemtype()));
			 orderDetailsMapper.updateByPrimaryKeySelective(orderDetails);
	     }
	     //更新执行开奖
	     cashRecord.setExecute(CashRecordEnum.EXECUTED.getCode());
	     cashRecordMapper.updateByPrimaryKeySelective(cashRecord);
     }
	
	//更新订单主表
	private void updateLotterOrder(LotteryOrder lotteryOrder) throws Exception{

		Map<String,Integer> result = orderDetailsMapper.findDetailWinning(lotteryOrder.getId());
		Integer not_winning = result.get("not_winning"); //未中奖
		if(not_winning > 0){
			lotteryOrder.setIswinning(IswinningEnum.NOT_WINNING.getCode());
			lotteryOrder.setUpdatedate(new Date());
			lotteryOrderMapper.updateByPrimaryKeySelective(lotteryOrder);
			return;
		}
		Integer close_winning = result.get("close_winning");//未开奖
		if(close_winning > 0){return;}
		
		//用户中奖
		lotteryOrder.setIswinning(IswinningEnum.ALREADY_WINNING.getCode());
		lotteryOrder.setUpdatedate(new Date());
	
	
		List<BigDecimal> bigdecList = orderDetailsMapper.findActualOddsByOid(lotteryOrder.getId());
		if(CollectionUtils.isEmpty(bigdecList)){
			//数据有误  抛出异常
			throw new Exception();
		}
		//总额
		long amount = BigdecimalUtil.amoutWinning(lotteryOrder.getMultiple(), bigdecList);
		//分润
		UserAccount userAccount = userAccountMapper.selectByPrimaryKey(lotteryOrder.getUid());
		
		long sharebenefit = BigdecimalUtil.sharebenefit(amount,userAccount.getHourselevel());
		long actualprize = amount - sharebenefit;
		lotteryOrder.setActualprize(actualprize);
		lotteryOrder.setSharebenefit(sharebenefit);
		lotteryOrderMapper.updateByPrimaryKeySelective(lotteryOrder);
		
		winpay_owner(lotteryOrder.getOwnerid(), sharebenefit,amount);
		winpay_user(lotteryOrder.getUid(), actualprize);
	}	
	
	
	/**
	 * 房主资金流水
	 * @param uid
	 * @param sharebenefit
	 * @throws Exception
	 */
	private void winpay_owner(Long ownerid , Long sharebenefit,Long amount) throws Exception{
		
		//第一步  新增流水
		UserAccount userAccount =userAccountMapper.selectByPrimaryKey(ownerid);
		WinPayFlowVo winpayflow_owner = new WinPayFlowVo();
		winpayflow_owner.setAmount(sharebenefit);
		winpayflow_owner.setAvailableBefore(userAccount.getAmount());
		long accbalance = sharebenefit.longValue() + userAccount.getAmount().longValue();
		winpayflow_owner.setAccbalance(accbalance);
		winpayflow_owner.setWinpay(WinpayEnum.WINPAY_IN.getCode());
		winpayflow_owner.setCreatedate(new Date());
		winpayflow_owner.setUid(ownerid);
		winpayflow_owner.setDesrType(WinpayflowEnum.ROOM_ROYALTY.getCode());
		winpayflowDao.insert(winpayflow_owner);
		
	    //第二部  修改账户信息
		//余额
		long  monkey  = userAccount.getAmount().longValue() + sharebenefit.longValue();
		userAccount.setAmount(monkey);
		//房间累计中奖金额
		long realywinmount = userAccount.getRealywinmount() + amount.longValue();
		userAccount.setRealywinmount(realywinmount);
		
		//提成
		long commission = userAccount.getCommission() + sharebenefit.longValue();
		userAccount.setCommission(commission);
		
		userAccountMapper.updateByPrimaryKeySelective(userAccount);
	}
	
	/**
	 * 用户资金流水
	 * @param uid
	 * @param actualprize
	 * @throws Exception
	 */
	private void winpay_user(Long uid ,Long actualprize) throws Exception{
		
		// 1 新增  资金流水
		UserAccount userAccount =userAccountMapper.selectByPrimaryKey(uid);
		WinPayFlowVo winpayflow_owner = new WinPayFlowVo();
		winpayflow_owner.setAmount(actualprize);
		winpayflow_owner.setAvailableBefore(userAccount.getAmount());
		long accbalance = actualprize.longValue() + userAccount.getAmount().longValue();
		winpayflow_owner.setAccbalance(accbalance);
		winpayflow_owner.setWinpay(WinpayEnum.WINPAY_IN.getCode());
		winpayflow_owner.setCreatedate(new Date());
		winpayflow_owner.setUid(uid);
		winpayflow_owner.setDesrType(WinpayflowEnum.PLATFORM_TRANSFER.getCode());
		winpayflowDao.insert(winpayflow_owner);
		
		//2 修改 账户信息 余额
		long  amount  = userAccount.getAmount().longValue() + actualprize.longValue();
		userAccount.setAmount(amount);
		
		//中奖总金额
		long winningamount = userAccount.getWinningamount().longValue() + actualprize.longValue();
		userAccount.setWinningamount(winningamount);
		
		//如果是房主  就计算个人红单率
		if(userAccount.getUtype() ==UserAccountTypeEunm.PUBLISHER.getCode()){
			Map<String,Integer> map = lotteryOrderMapper.findRedrate(uid, AvailableEnum.AVAILABLE.getCode());
			int already_winning = map.get("already_winning");
			int not_winning =map.get("not_winning");
			userAccount.setRedrate(BigdecimalUtil.CalRedRate(already_winning,not_winning));
		}
		userAccountMapper.updateByPrimaryKeySelective(userAccount);
	}
	
	
}
